﻿namespace NTLib.WPF
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Threading;

    /// <summary>
    /// 
    /// </summary>
    public static class DispatchHelper
    {
        #region Fields

        private static Dispatcher s_dispatcher;

        #endregion

        #region Ctor
        #endregion

        #region Properties

        /// <summary>
        /// Gets the UI dispatcher.
        /// </summary>
        public static Dispatcher UIDispatcher
        {
            get
            {
                if (s_dispatcher == null)
                {
                    if (Application.Current == null)
                        s_dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
                    else
                        s_dispatcher = Application.Current.Dispatcher;
                }
                return s_dispatcher;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Execut the action in the dispatcher context.
        /// </summary>
        /// <param name="action">The action.</param>
        public static void DispatchExec(this Action action)
        {
            var dispatcher = UIDispatcher;
            if (Thread.CurrentThread.ManagedThreadId == dispatcher.Thread.ManagedThreadId)
                action();
            else
                dispatcher.Invoke(action);
        }

        /// <summary>
        /// Execut the action in the dispatcher context.
        /// </summary>
        /// <param name="asyncaction">The async action.</param>
        /// <param name="token">The cancellation token.</param>
        public static async Task DispatchExecAsync(this Func<CancellationToken, Task> asyncaction, CancellationToken token = default(CancellationToken))
        {
            var dispatcher = UIDispatcher;
            if (Thread.CurrentThread.ManagedThreadId == dispatcher.Thread.ManagedThreadId)
                await asyncaction(token);
            else
                await dispatcher.BeginInvoke(asyncaction, token);
        }

        /// <summary>
        /// Execut the action in the dispatcher context.
        /// </summary>
        /// <param name="asyncaction">The asyncaction.</param>
        /// <param name="token">The token.</param>
        /// <returns></returns>
        public static async Task DispatchExecAsync(this Action<CancellationToken> asyncaction, CancellationToken token = default(CancellationToken))
        {
            var dispatcher = UIDispatcher;
            if (Thread.CurrentThread.ManagedThreadId == dispatcher.Thread.ManagedThreadId)
                asyncaction(token);
            else
                await dispatcher.BeginInvoke(asyncaction, token);
        }

        #endregion
    }
}
